#include "stdio.h"
#include "string.h"
#include "stdint.h"

#include "usrAtHandle.h"

#include "usrList.h"
#include "usrError.h"   

#define AT_CMD_LEN  11

#define AT_SEND_DATA_LEN        50
#define AT_RECV_DATA_MIN_LEN    50   
#define AT_RECV_DATA_MAX_LEN    120
#define AT_ONCE_RECV_MAX_LEN    200

typedef struct AtCmd
{
    char                cmd[AT_CMD_LEN];
    uint8_t             cmdId;
    void*     					p_cb;
}AtCmd_t;

typedef struct atRecvBuff
{
    uint8_t     recvBuff[AT_ONCE_RECV_MAX_LEN];
    uint8_t*    p_BuffStart;
    int         len;
}atRecvBuff_t;


typedef int (*atCmdSendHandle)(const AtCmd_t* p_cmd, char* data, int len);
typedef uint8_t (*sendDatHandle)(char* p_dat, int len);
typedef uint8_t (*recvDatHandle)(char* p_dat, int* len);


uint8_t atCmdTest(const AtCmd_t* p_cmd, char* data, int len);
uint8_t atCmdVersion(const AtCmd_t* p_cmd, char* data, int len);
uint8_t atCmdMode(const AtCmd_t* p_cmd, char* data, int len);
uint8_t atCmdConnWifi(const AtCmd_t* p_cmd, char* data, int len);
uint8_t atCmdGetIpMac(const AtCmd_t* p_cmd, char* data, int len);
uint8_t atCmdConTcp(const AtCmd_t* p_cmd, char* data, int len);
uint8_t atCmdCipInit(const AtCmd_t* p_cmd, char* data, int len);
uint8_t atCmdCipStart(const AtCmd_t* p_cmd, char* data, int len);
uint8_t atCmdCipSendDat(const AtCmd_t* p_cmd, char* data, int len);
uint8_t atCmdCipEnd(const AtCmd_t* p_cmd, char* data, int len);

sendDatHandle   p_sendDatHandle;
recvDatHandle   p_recvDatHandle;

const AtCmd_t atHandleArrary[] = {
    {.cmdId= AT_CMD_TEST,       .cmd = NULL,        .p_cb = atCmdTest},
    {.cmdId= AT_CMD_GMR,        .cmd = "GMR",       .p_cb = atCmdVersion},
    {.cmdId= AT_CMD_CWMODE,     .cmd = "CWMODE",    .p_cb = atCmdMode},
    {.cmdId= AT_CMD_CWJAP,      .cmd = "CWJAP",     .p_cb = atCmdConnWifi},
    {.cmdId= AT_CMD_CIFSR,      .cmd = "CIFSR",     .p_cb = atCmdGetIpMac},
    {.cmdId= AT_CMD_CIPSTART,   .cmd = "CIPSTART",  .p_cb = atCmdConTcp},
    {.cmdId= AT_CMD_CIPMODE,    .cmd = "CIPMODE",   .p_cb = atCmdCipInit},
    {.cmdId= AT_CMD_CIPSEND,    .cmd = "CIPSEND",   .p_cb = atCmdCipStart},
    {.cmdId= AT_CIP_SEND_DATA,  .cmd = NULL,        .p_cb = atCmdCipSendDat},
    {.cmdId= AT_CIP_END,        .cmd = NULL,        .p_cb = atCmdCipEnd},
};

uint8_t CipFlag = 0;

static atRecvBuff_t socketBuff;


uint8_t atCmdTest(const AtCmd_t* p_cmd, char* data, int len)
{
    char  sendDat[AT_SEND_DATA_LEN] = "\0";
    char  recvDat[AT_RECV_DATA_MIN_LEN] = "\0";
    uint8_t ret = USR_SUCCESS;
    int32_t recvLen = 0;

    sprintf(sendDat, "AT\r\n"); 
    ret = p_sendDatHandle(sendDat, strlen(sendDat));
    if(ret == USR_AT_CMD_SEND_ERROR)
        return ret;

    while (p_recvDatHandle(recvDat, &recvLen) != USR_SUCCESS);
      
    return ret;
}

uint8_t atCmdVersion(const AtCmd_t* p_cmd, char* data, int len)
{
    char  sendDat[AT_SEND_DATA_LEN] = "\0";
    char  recvDat[AT_RECV_DATA_MAX_LEN] = "\0";
    uint8_t ret = USR_SUCCESS;
    int32_t recvLen = 0;

    sprintf(sendDat, "AT+%s\r\n", p_cmd->cmd); 

	ret = p_sendDatHandle(sendDat, strlen(sendDat));
    if(ret == USR_AT_CMD_SEND_ERROR)
        return ret;

    while (p_recvDatHandle(recvDat, &recvLen) != USR_SUCCESS);
    
    return ret;
}

uint8_t atCmdMode(const AtCmd_t* p_cmd, char* data, int len)
{
    char  sendDat[AT_SEND_DATA_LEN] = "\0";
    char  recvDat[AT_RECV_DATA_MIN_LEN] = "\0";
    uint8_t ret = USR_SUCCESS;
    int32_t recvLen = 0;
    
    sprintf(sendDat, "AT+%s=1\r\n", p_cmd->cmd); 

	ret = p_sendDatHandle(sendDat, strlen(sendDat));
    if(ret == USR_AT_CMD_SEND_ERROR)
        return ret;

    while (p_recvDatHandle(recvDat, &recvLen) != USR_SUCCESS);
    
    return ret;
}

uint8_t atCmdConnWifi(const AtCmd_t* p_cmd, char* data, int len)
{
    char  sendDat[AT_SEND_DATA_LEN] = "\0";
    char  recvDat[AT_RECV_DATA_MIN_LEN] = "\0";
    uint8_t ret = USR_SUCCESS;
    int32_t recvLen = 0;

    sprintf(sendDat, "AT+%s=\"%s\",\"%s\"\r\n", p_cmd->cmd, ((wifiConfig_t*)data)->ssid, ((wifiConfig_t*)data)->pwd); 

	ret = p_sendDatHandle(sendDat, strlen(sendDat));
    if(ret == USR_AT_CMD_SEND_ERROR)
        return ret;

    while (p_recvDatHandle(recvDat, &recvLen) != USR_SUCCESS);
    
    while (p_recvDatHandle(recvDat, &recvLen) != USR_SUCCESS);

    return ret;
}

uint8_t atCmdGetIpMac(const AtCmd_t* p_cmd, char* data, int len)
{
	char  sendDat[AT_SEND_DATA_LEN] = "\0";
    char  recvDat[AT_RECV_DATA_MAX_LEN] = "\0";
    uint8_t ret = USR_SUCCESS;
    int32_t recvLen = 0;

    sprintf(sendDat, "AT+%s\r\n", p_cmd->cmd); 

	ret = p_sendDatHandle(sendDat, strlen(sendDat));
    if(ret == USR_AT_CMD_SEND_ERROR)
        return ret;

    while (p_recvDatHandle(recvDat, &recvLen) != USR_SUCCESS);
    
    printf("%s\r\n", recvDat);

    return ret;
}

uint8_t atCmdConTcp(const AtCmd_t* p_cmd, char* data, int len)
{
    char  sendDat[AT_SEND_DATA_LEN] = "\0";
    char  recvDat[AT_RECV_DATA_MIN_LEN] = "\0";
    uint8_t ret = USR_SUCCESS;
    int32_t recvLen = 0;
    
    sprintf(sendDat, "AT+%s=\"TCP\",\"%s\",%d\r\n", p_cmd->cmd, ((tcpConfig_t*)data)->ip, ((tcpConfig_t*)data)->port); 

	ret = p_sendDatHandle(sendDat, strlen(sendDat));
    if(ret == USR_AT_CMD_SEND_ERROR)
        return ret;

    while (p_recvDatHandle(recvDat, &recvLen) != USR_SUCCESS);
    while (p_recvDatHandle(recvDat, &recvLen) != USR_SUCCESS);
    
    return ret;
}

uint8_t atCmdCipInit(const AtCmd_t* p_cmd, char* data, int len)
{
    char  sendDat[AT_SEND_DATA_LEN] = "\0";
    char  recvDat[AT_RECV_DATA_MIN_LEN] = "\0";
    uint8_t ret = USR_SUCCESS;
    int32_t recvLen = 0;

    sprintf(sendDat, "AT+%s=1\r\n", p_cmd->cmd); 

	ret = p_sendDatHandle(sendDat, strlen(sendDat));
    if(ret == USR_AT_CMD_SEND_ERROR)
        return ret;

    while (p_recvDatHandle(recvDat, &recvLen) != USR_SUCCESS);

    return ret;
}

uint8_t atCmdCipStart(const AtCmd_t* p_cmd, char* data, int len)
{
    char  sendDat[AT_SEND_DATA_LEN] = "\0";
    char  recvDat[AT_RECV_DATA_MIN_LEN] = "\0";
    uint8_t ret = USR_SUCCESS;
    int32_t recvLen = 0;

    sprintf(sendDat, "AT+%s\r\n", p_cmd->cmd); 

	ret = p_sendDatHandle(sendDat, strlen(sendDat));
    if(ret == USR_AT_CMD_SEND_ERROR)
        return ret;

    while (p_recvDatHandle(recvDat, &recvLen) != USR_SUCCESS);

    CipFlag = 1;
    return ret;
}

uint8_t atCmdCipSendDat(const AtCmd_t* p_cmd, char* data, int len)
{
    uint8_t ret = USR_SUCCESS;

    if(CipFlag == 0)
        return USR_CIP_NOT_START;
    ret = p_sendDatHandle(data, len);
    if(ret == USR_AT_CMD_SEND_ERROR)
        return ret;

    return ret;
}

uint8_t atCmdCipEnd(const AtCmd_t* p_cmd, char* data, int len)
{
    uint8_t ret = USR_SUCCESS;
    char  sendDat[] = "+++";

    if(CipFlag == 0)
        return USR_CIP_NOT_START;
    
    ret = p_sendDatHandle(sendDat, strlen(sendDat));
    if(ret == USR_AT_CMD_SEND_ERROR)
        return ret;
    CipFlag = 0;

    return ret;
}

uint8_t usrSendAtCmd(uint8_t cmdId, char* p_dat, int len)
{
    for (size_t i = 0; i < AT_CMD_MAX; i++)
    {
        if(cmdId == atHandleArrary[i].cmdId)
        {
            return ((atCmdSendHandle)atHandleArrary[i].p_cb)(&atHandleArrary[i], p_dat, len);
        }
    }
    
	return USR_AT_CMD_ID_ERROR;
} 

int usrSend(int fd, char* p_dat, size_t len, int flags)
{
    if (flags != 0)
    {
        printf("-----send flags %d------\r\n", flags);
    }
    if(usrSendAtCmd(AT_CIP_SEND_DATA, p_dat, len) == USR_SUCCESS)
        return len;
    else
        return -1;
}


int usrRecv(int fd, char* buf, size_t len, int flags)
{
    int ret;
    int recvLen = 0;
    if (flags != 0)
    {
        printf("-----recv flags %d------\r\n", flags);
    }

    if(socketBuff.len == 0)
    {
        ret = p_recvDatHandle((char*)socketBuff.recvBuff, &socketBuff.len);
        if(ret != USR_SUCCESS)
            return 0;
        socketBuff.p_BuffStart = socketBuff.recvBuff;
    }
    // printf("recv1 %d %d\r\n", len, socketBuff.len);
    
    if(socketBuff.len < len)
        recvLen = socketBuff.len;
    else
        recvLen = len;

    for (size_t i = 0; i < recvLen; i++)
    {
        buf[i] = socketBuff.p_BuffStart[i];
    }
    socketBuff.len -= recvLen;
    socketBuff.p_BuffStart += recvLen;
    // printf("recv2 %d %d\r\n", len, socketBuff.len);

    return recvLen;
}


void usrAtInit(void* p1, void* p2)
{
    if(p1 == NULL || p2 == NULL)
    {
        printf("usrAtInit error\r\n");
        return;
    }

    p_sendDatHandle = (sendDatHandle)p1;
    p_recvDatHandle = (recvDatHandle)p2;

    socketBuff.len = 0;
    socketBuff.p_BuffStart =NULL;
}


